Imports ZedGraph

Namespace Controls
    Public NotInheritable Class GraphContainer
        Implements DataStream.IStreamConfig, DataStream.IStreamRecieve, IDisposable, DataStream.IStreamHandle

        Private mGraphSettings As New GraphContainerSettingCollection
        Private mItemRouter As New GraphItemRouter
        Private mGraphNames As New GraphNameCollection

        ' Timer Based state variables
        Private mDataRefreshTime As Integer = 2000
        Private mDataRefreshBuffer As Boolean = False
        Private WithEvents mDataRefreshTimer As New System.Timers.Timer

        '  Dim mXAxis As ZedGraph.XAxis = Nothing

        Private mXzoom As UInt32 = 1000

        Const MaxPaneCount As Integer = 6

        Private mZoomEnabled As Boolean = True

        Private mGetCurrentStream As DataStream.IStreamHandle.GetCurrentLog = Nothing

        Sub New()
            ' This call is required by the Windows Form Designer.
            InitializeComponent()

            ' Add any initialization after the InitializeComponent() call.
            mDataRefreshTimer.Interval = mDataRefreshTime

        End Sub

        Private Sub GraphContainer_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            ' Clear out the current pane lists!
            RefreshNewSettings()

            Me.GraphNameCollectionBindingSource.RaiseListChangedEvents = True
            Me.GraphNameCollectionBindingSource.DataSource = mGraphNames

            Me.GraphContainerSettingCollectionBindingSource.RaiseListChangedEvents = True
            Me.GraphContainerSettingCollectionBindingSource.DataSource = Me.mGraphSettings

            InitialiseGraph()

            InitialiseDataGrid()

        End Sub

#Region "Graph Drawing Functions"
        Private Sub InitialiseGraphPanes()
            Dim master As ZedGraph.MasterPane = Me.uxZedGraph.MasterPane
            master.PaneList.Clear()

            For i As Integer = 1 To mGraphSettings.PaneCount
                Dim pane As ZedGraph.GraphPane = New ZedGraph.GraphPane(New RectangleF(uxZedGraph.Location, uxZedGraph.Size), "Graph" & i, "", "")
                master.PaneList.Add(pane)
                pane.Border.IsVisible = False
                pane.Legend.IsVisible = False
                pane.XAxis.Type = AxisType.Linear
                pane.XAxis.Scale.MaxGrace = 0

                AddHandler pane.XAxis.ScaleFormatEvent, AddressOf uxZedGraph_Pane_FormatScaleText
                pane.X2Axis.Scale.MaxGrace = 0

                pane.XAxis.Scale.FontSpec.Size = 16
                pane.YAxis.Scale.FontSpec.Size = 16
                pane.X2Axis.Scale.FontSpec.Size = 16
                pane.Y2Axis.Scale.FontSpec.Size = 16
                pane.Title.FontSpec.Size = 20
            Next

            ' Perform the layout
            master.SetLayout(uxZedGraph.CreateGraphics, ZedGraph.PaneLayout.SingleColumn)
            master.DoLayout(uxZedGraph.CreateGraphics)
        End Sub

        Private Sub InitialiseDataGrid()
            mGraphNames.Clear()

            For i As Integer = 1 To MaxPaneCount
                mGraphNames.Add(New GraphName("Graph" & i))
            Next
            'For Each pane As ZedGraph.GraphPane In uxZedGraph.MasterPane.PaneList
            '    mGraphNames.Add(New GraphName(pane.Title.Text))
            'Next

            mGraphNames.Add(New GraphName("None"))

        End Sub

        Private Sub InitialiseGraph()
            Me.uxZedGraph.GraphPane.XAxis.Type = AxisType.Linear
            Me.uxZedGraph.MasterPane.IsPenWidthScaled = False
            Me.uxZedGraph.IsEnableVPan = False
            ' Me.uxZedGraph.IsEnableVZoom = False
        End Sub

        Private Sub InitialiseGraphItem(ByVal Item As GraphContainerSetting)
            If mItemRouter.Contains(Item.Name) Then
                If mItemRouter(Item.Name).Pane.Title.Text <> Item.BoundPane Then
                    ' Find line in other pane and remove it
                    mItemRouter(Item.Name).Pane.CurveList.Remove(mItemRouter(Item.Name).Line)
                    Me.uxZedGraph.Invalidate(New Region(mItemRouter(Item.Name).Pane.Rect))
                    mItemRouter.Remove(Item.Name)
                ElseIf mItemRouter(Item.Name).Line.Color <> Item.Colour Then
                    ' Update the colour!
                    mItemRouter(Item.Name).Line.GetYAxis(mItemRouter(Item.Name).Pane).Color = Item.Colour
                    mItemRouter(Item.Name).Line.Color = Item.Colour
                Else
                    Return
                End If
                ' find it and check if its the same? do something appropriate here... move it etc?
            End If
            If Item.BoundPane <> "" AndAlso Not uxZedGraph.MasterPane.PaneList(Item.BoundPane) Is Nothing Then
                Dim pane As GraphPane = uxZedGraph.MasterPane.PaneList(Item.BoundPane)

                If Not pane.CurveList.IndexOf(Item.Name) >= 0 Then
                    Dim points As New PointPairList
                    Dim line As LineItem = pane.AddCurve(Item.Name, points, Item.Colour, SymbolType.None)
                    line.Tag = Item

                    line.Line.Width = 2

                    ' Initialise the route to the pane
                    Dim Route As New GraphItemRoute(Item.Name, pane, line, Item)
                    mItemRouter.Add(Route)

                    ' Get all current values from the current stream!
                    If Not mGetCurrentStream Is Nothing AndAlso _
                     Not mGetCurrentStream.Invoke Is Nothing Then
                        Dim log As BikiSoft.DataStream.StreamLog = mGetCurrentStream.Invoke
                        For i As Integer = 0 To log.Count - 1
                            If log(i).contains(Item.Name) Then
                                RouteGraphItem(Route, log(i)(Item.Name))
                                ' Debug.Print("Item: " & Item.Name & " Value:" & log(i)(Item.Name).Value)
                            End If
                        Next
                    End If
                End If
            End If
        End Sub

        Private Sub RouteGraphItem(ByVal Route As GraphItemRoute, ByVal Item As DataStream.StreamItem)
            'Debug.Print("Item {0} routed to {1}", Item.Name, Route.Pane.Title.Text)
            Dim pane As ZedGraph.GraphPane = Route.Pane
            Dim line As LineItem = Route.Line
            If Route.Line.NPts <= 0 Then
                ' Initialise the axis'
                Dim YAxis As ZedGraph.Axis

                pane.XAxis.IsAxisSegmentVisible = True
                Dim idx As Integer = pane.YAxisList.IndexOf(Item.ItemUnit)
                If idx >= 0 Then
                    YAxis = pane.YAxisList(Item.ItemUnit)
                    line.IsY2Axis = False
                    line.YAxisIndex = idx
                    YAxis.Color = Color.Black
                Else
                    idx = pane.Y2AxisList.IndexOf(Item.ItemUnit)

                    If idx >= 0 Then
                        YAxis = pane.Y2AxisList(Item.ItemUnit)
                        line.IsY2Axis = True
                        line.YAxisIndex = idx
                        pane.Y2Axis.IsVisible = True
                        YAxis.Color = Color.Black
                    Else
                        ' Create a new Scale!
                        If pane.Y2Axis.Title.Text <> "" AndAlso pane.YAxis.Title.Text <> "" Then
                            If pane.Y2AxisList.Count >= pane.YAxisList.Count Then
                                YAxis = New YAxis(Item.ItemUnit)
                                pane.YAxisList.Add(YAxis)
                                line.IsY2Axis = False
                                line.YAxisIndex = pane.YAxisList.IndexOf(Item.ItemUnit)
                            Else
                                YAxis = New Y2Axis(Item.ItemUnit)
                                pane.Y2AxisList.Add(YAxis)
                                ' YAxis.IsVisible = True
                                line.IsY2Axis = True
                                pane.Y2Axis.IsVisible = True
                                line.YAxisIndex = pane.Y2AxisList.IndexOf(Item.ItemUnit)
                            End If
                        Else
                            If pane.YAxis.Title.Text = "" Then
                                'First Index Y1
                                YAxis = pane.YAxis
                                line.IsY2Axis = False
                            Else
                                'First Index Y2
                                YAxis = pane.Y2Axis
                                pane.Y2Axis.IsVisible = True
                                line.IsY2Axis = True
                            End If
                            YAxis.Title.Text = Item.ItemUnit
                            line.YAxisIndex = 0
                        End If

                        YAxis.Color = Route.Line.Color
                        YAxis.Scale.Min = Item.ItemMin
                        YAxis.Scale.Max = Item.ItemMax
                        YAxis.IsVisible = True
                        YAxis.Scale.MinAuto = Item.ItemAuto
                        YAxis.Scale.MaxAuto = Item.ItemAuto
                        YAxis.Scale.MinGrace = Item.ItemMin - ((Item.ItemMax - Item.ItemMin) * 0.05)
                        YAxis.Scale.MaxGrace = Item.ItemMax + ((Item.ItemMax - Item.ItemMin) * 0.05)

                    End If
                End If

                Debug.Print("Axis Initialised!")


            End If

            ' Draw the actual line


            'Route.Line.AddPoint(Item.TimeStamp.ToOADate, Item.RawValue)
            Route.Line.AddPoint(Item.Index, Item.RawValue)
            'Dim beginDate As New DateTime(1899, 12, 31, 0, 0, 0)
            'Dim datediff As TimeSpan = Item.TimeStamp.Subtract(beginDate)
            'Dim OAdate As Double = CInt(datediff.TotalDays)
            'OAdate += datediff.Hours / 24.0
            'OAdate += datediff.Minutes / 1440.0
            'OAdate += datediff.Seconds / 86400.0
            'OAdate += datediff.Milliseconds / 86400000.0
            ''Dim blah As Double = Item.TimeStamp.ToOADate 'New XDate(Item.TimeStamp.Year, Item.TimeStamp.Month, Item.TimeStamp.Day, Item.TimeStamp.Hour, Item.TimeStamp.Minute, Item.TimeStamp.Second, Item.TimeStamp.Millisecond)

            'Console.WriteLine("Xaxus: " & OAdate)
            'Route.Line.AddPoint(OAdate, Item.RawValue)
            'Route.Line.AddPoint(New XDate(Item.TimeStamp.Year, Item.TimeStamp.Month, Item.TimeStamp.Day, Item.TimeStamp.Hour, Item.TimeStamp.Minute, Item.TimeStamp.Second, Item.TimeStamp.Millisecond), Item.RawValue)

            ' Console.WriteLine(Item.TimeStamp.ToLongTimeString)

            ' Set the ranges
            If Not pane.IsZoomed Then
                pane.XAxis.Scale.Max = Item.Index
                pane.XAxis.Scale.Min = pane.XAxis.Scale.Max - mXzoom
            End If

            Me.uxZedGraph.SetScrollRangeFromData()

            '  RaiseEvent Restrict(Me, New BikiSoft.DataStream.StreamRestrictEventArgs(pane.XAxis.Scale.Min, pane.XAxis.Scale.Max))

            If Not TimerRequired() Then
                RefreshGraphPanes()
            End If
            '  Route.Pane.AxisChange()
        End Sub

        Private Delegate Sub RefreshDelegate(ByVal item As Region)
        Private Sub RefreshGraphPanes()
            Dim cnt As Integer = 0
            For i As Integer = 0 To Me.uxZedGraph.MasterPane.PaneList.Count - 1
                Me.uxZedGraph.MasterPane.PaneList(i).AxisChange()
                If Me.uxZedGraph.InvokeRequired Then
                    Me.Invoke(New RefreshDelegate(AddressOf Me.uxZedGraph.Invalidate), New Object() {New Region(Me.uxZedGraph.MasterPane.PaneList(i).Rect)})
                Else
                    Debug.Print("Refeshing Graph Panes")
                    Try
                        If cnt <= Me.mGraphSettings.PaneCount Then
                            Me.uxZedGraph.Invalidate(New Region(Me.uxZedGraph.MasterPane.PaneList(i).Rect))
                        End If
                    Catch ex As Exception
                    Finally
                        GC.Collect()
                    End Try
                End If
            Next
        End Sub

        Private Function TimerRequired() As Boolean
            If mDataRefreshTimer.Enabled Then
                mDataRefreshBuffer = True
                Return True
            Else
                If Not MyBase.IsDisposed Then
                    If mDataRefreshTime > 0 Then mDataRefreshTimer.Start()
                End If
                Return False
            End If
        End Function

        Private Sub TimerElapse(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs) Handles mDataRefreshTimer.Elapsed
            mDataRefreshTimer.Stop()
            If mDataRefreshBuffer Then
                RefreshGraphPanes()
            End If
        End Sub

        Private Function uxZedGraph_PointValueEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal pane As ZedGraph.GraphPane, ByVal curve As ZedGraph.CurveItem, ByVal iPt As System.Int32) As System.String Handles uxZedGraph.PointValueEvent
            Dim config As GraphContainerSetting = CType(curve.Tag, GraphContainerSetting)
            Dim time As String
            If Not mGetCurrentStream Is Nothing Then
                Dim tm As Date
                If pane.XAxis.Scale.Type = AxisType.Linear Or _
                pane.XAxis.Scale.Type = AxisType.LinearAsOrdinal Then
                    tm = mGetCurrentStream.Invoke()(curve.Points(iPt).X).TimeStamp
                ElseIf pane.XAxis.Scale.Type = AxisType.Date Or _
                pane.XAxis.Scale.Type = AxisType.DateAsOrdinal Then
                    tm = DateTime.FromOADate(curve.Points(iPt).X)
                End If

                time = tm.ToString("dd-MM-yy HH:MM:ss.fff")

                Return String.Format("Item: {0} Value: {1} {2} @ {3}", config.Name, String.Format("{0:N1}", curve.Points(iPt).Y), curve.GetYAxis(pane).Title.Text, time)
            Else
                Return String.Format("Item: {0} Value: {1} {2}", config.Name, curve.Points(iPt).Y, curve.GetYAxis(pane).Title.Text)
            End If
        End Function

        Private Function uxZedGraph_Pane_FormatScaleText(ByVal pane As ZedGraph.GraphPane, ByVal axis As ZedGraph.Axis, ByVal val As Double, ByVal index As Integer) As String
            Dim tm As Date
            Dim time As String
            If index >= 0 AndAlso Not mGetCurrentStream Is Nothing AndAlso Not mGetCurrentStream.Invoke Is Nothing AndAlso mGetCurrentStream.Invoke.Count > index Then
                tm = mGetCurrentStream.Invoke()(index).TimeStamp

                time = tm.ToString("dd-MM-yy HH:MM:ss.fff")
            Else
                time = ""
            End If
            Return time
        End Function

#End Region

#Region "DataGrid events and functions"
        ''' <summary>
        ''' Causes a complete refresh of all controls
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub RefreshNewSettings()
            ' Clear all existing routes out
            mDataRefreshTimer.Stop()

            mItemRouter.Clear()

            InitialiseGraphPanes()

            SortItems()

            ' Go through the list and re-create the routes
            For Each item As GraphContainerSetting In Me.mGraphSettings
                If item.BoundPane <> "" Then
                    InitialiseGraphItem(item)
                End If
            Next

            Me.uxZedGraph.Refresh()

        End Sub

        Private Sub SortItems()
            Me.GraphContainerSettingCollectionBindingSource.RaiseListChangedEvents = False
            Me.GraphContainerSettingCollectionBindingSource.SuspendBinding()
            mGraphSettings.Sort(Nothing)
            Me.GraphContainerSettingCollectionBindingSource.ResumeBinding()
            Me.GraphContainerSettingCollectionBindingSource.RaiseListChangedEvents = True
        End Sub

        Public Sub InitialiseValidItems(ByVal Items() As String) Implements DataStream.IStreamConfig.InitialiseValidItems
            Dim colours As String() = {"Aqua", "Aquamarine", "Black", "Blue", "BlueViolet", _
"Brown", "BurlyWood", "CadetBlue", "Chartreuse", "Chocolate", "Coral", "CornflowerBlue", "Crimson", "Cyan", "DarkBlue", _
"DarkCyan", "DarkGoldenrod", "DarkGray", "DarkGreen", "DarkKhaki", "DarkMagenta", "DarkOliveGreen", "DarkOrange", "DarkOrchid", _
"DarkRed", "DarkSalmon", "DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkTurquoise", "DarkViolet", "DeepPink", _
"DeepSkyBlue", "DodgerBlue", "Firebrick", "ForestGreen", "Fuchsia", "Gainsboro", "Gold", _
"Goldenrod", "Green", "GreenYellow", "HotPink", "IndianRed", "Indigo", "Khaki", _
"LawnGreen", _
"Magenta", "Maroon", "MediumAquamarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen", "MediumSlateBlue", _
"MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue", "Moccasin", _
"Navy", "OldLace", "OliveDrab", "Orange", "OrangeRed", "Orchid", "PaleGoldenrod", "PaleGreen", "PaleVioletRed", _
"PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "Red", "RosyBrown", "RoyalBlue", "SaddleBrown", "Salmon", _
"SandyBrown", "SeaGreen", "SeaShell", "Sienna", "SkyBlue", "SlateBlue", "SlateGray", "Snow", "SpringGreen", "SteelBlue", _
"Teal", "Thistle", "Tomato", "Turquoise", "Violet", "Wheat", "WhiteSmoke", "Yellow", "YellowGreen"}

            Dim coloursCnt As Integer = 0

            For Each str As String In Items
                If Not str Is Nothing Then
                    If Not mGraphSettings.Contains(str) Then
                        mGraphSettings.Add(New GraphContainerSetting(str, Color.FromName(colours(coloursCnt)), ""))
                        coloursCnt += 1
                    End If
                End If
            Next

            SortItems()

            ' re-initialise the datagrid as the settings have changed
            '  InitialiseDataGrid()
        End Sub

        Private Sub uxGraphSettings_CellValueChanged(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles uxGraphSettings.CellValueChanged
            If e.RowIndex >= 0 And e.ColumnIndex >= 0 Then
                Dim dg As DataGridView = CType(sender, DataGridView)
                Dim item As GraphContainerSetting = CType(CType(dg.DataSource, BindingSource)(e.RowIndex), GraphContainerSetting)
                InitialiseGraphItem(item)
            End If
        End Sub

        Private Sub uxGraphSettings_DataError(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles uxGraphSettings.DataError
            e.ThrowException = False
        End Sub
#End Region

#Region "Interface Functions"

        ''' <summary>
        ''' Sets a cursor on the current seeked position
        ''' </summary>
        ''' <param name="Stream"></param>
        ''' <remarks></remarks>
        Public Sub RecieveSeek(ByVal Stream As DataStream.Stream) Implements DataStream.IStreamRecieve.RecieveSeek

        End Sub

        Public ReadOnly Property StreamItems() As KeyedStringCollectionWithEvents Implements DataStream.IStreamConfig.StreamControlItems
            Get
                Return Nothing
            End Get
        End Property

        Public Sub RecieveStream(ByVal Stream As DataStream.Stream) Implements DataStream.IStreamRecieve.RecieveStream
            Dim item As DataStream.StreamItem
            If Not MyBase.IsDisposed AndAlso Stream.Index >= 0 AndAlso mItemRouter.Count > 0 Then
                For Each route As GraphItemRoute In Me.mItemRouter
                    item = Stream(route.StreamItemName)
                    If Not IsNothing(item) Then
                        RouteGraphItem(route, item)
                    End If
                    'If Stream.contains(route.StreamItemName) Then

                    'End If
                Next
            End If
        End Sub

        Public Event RequestRefresh(ByVal sender As Object, ByVal e As System.EventArgs) Implements DataStream.IStreamRecieve.RequestRefresh

        Public Event Restrict(ByVal sender As Object, ByVal e As DataStream.StreamRestrictEventArgs) Implements DataStream.IStreamRecieve.Restrict

        Public Event Seek(ByVal sender As Object, ByVal e As DataStream.StreamSeekEventArgs) Implements DataStream.IStreamRecieve.Seek

        Public ReadOnly Property Name1() As String Implements INamed.Name
            Get
                Return MyBase.Name
            End Get
        End Property

        Public Property StreamControlData() As Byte() Implements DataStream.IStreamConfig.StreamControlData
            Get
                If Not IsNothing(mGraphSettings) Then
                    Dim loader As New Modules.ObjectPersistance(Of GraphContainerSettingCollection)
                    Dim stream As IO.Stream = Nothing

                    ' Compress and serialise
                    loader.SaveToStreamAndCompress(stream, mGraphSettings)

                    ' Save the bytes
                    Dim bytes(stream.Length - 1) As Byte
                    stream.Read(bytes, 0, stream.Length)
                    stream.Close()
                    Return bytes
                Else
                    Return Nothing
                End If
            End Get
            Set(ByVal value As Byte())
                If Not IsNothing(value) AndAlso value.Length > 0 Then
                    Dim loader As New Modules.ObjectPersistance(Of GraphContainerSettingCollection)
                    Dim stream As GraphContainerSettingCollection = Nothing

                    ' uncompress and deserialise
                    loader.LoadFromStreamAndUnCompress(New IO.MemoryStream(value), stream)

                    If Not IsNothing(stream) Then
                        ' Set the settings and cause a Initialise
                        mGraphSettings.Clear()

                        stream.CopyTo(mGraphSettings)

                        mGraphSettings.PaneCount = stream.PaneCount

                        RefreshNewSettings()
                    End If

                End If
            End Set
        End Property

        Public Property DataRefreshTime() As Integer Implements DataStream.IStreamConfig.DataRefreshTime
            Get
                Return mDataRefreshTime
            End Get
            Set(ByVal value As Integer)
                mDataRefreshTime = value
                If value > 0 Then
                    mDataRefreshTimer.Interval = value
                End If
            End Set
        End Property
#End Region

#Region "Private Classes"
        Private Class GraphItemRouter
            Inherits KeyedCollectionWithEvents(Of String, GraphItemRoute)

            Protected Overrides Function GetKeyForItem(ByVal item As GraphItemRoute) As String
                Return item.StreamItemName
            End Function

            Public Overrides Sub GetObjectDataAdditionalSerialization(ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext)

            End Sub

            Public Overrides Sub NewAdditionalDeserialization(ByVal Info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext)

            End Sub
        End Class

        Private Class GraphItemRoute
            Private mStreamName As String
            Private mPane As ZedGraph.GraphPane
            Private mLine As ZedGraph.LineItem
            Private mConfig As GraphContainerSetting

            Sub New(ByVal StreamItemName As String, ByVal Pane As ZedGraph.GraphPane, ByVal Line As ZedGraph.LineItem, ByVal Config As GraphContainerSetting)
                mStreamName = StreamItemName
                mPane = Pane
                mLine = Line
                mConfig = Config
            End Sub

            Public ReadOnly Property Config() As GraphContainerSetting
                Get
                    Return mConfig
                End Get
            End Property
            Public ReadOnly Property StreamItemName() As String
                Get
                    Return mStreamName
                End Get
            End Property

            Public ReadOnly Property Pane() As ZedGraph.GraphPane
                Get
                    Return mPane
                End Get
            End Property

            Public ReadOnly Property Line() As ZedGraph.LineItem
                Get
                    Return mLine
                End Get
            End Property

        End Class
#End Region

        Public Property GetCurrentStreamLog() As DataStream.IStreamHandle.GetCurrentLog Implements DataStream.IStreamHandle.GetCurrentStreamLog
            Get
                Return mGetCurrentStream
            End Get
            Set(ByVal value As DataStream.IStreamHandle.GetCurrentLog)
                mGetCurrentStream = value
            End Set
        End Property

        ''' <summary>
        ''' Use this to hide the configuration!
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function uxZedGraph_DoubleClickEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal e As System.Windows.Forms.MouseEventArgs) As System.Boolean Handles uxZedGraph.DoubleClickEvent
            If Me.uxSplitContainer.Panel2Collapsed Then
                Me.uxSplitContainer.Panel2Collapsed = False
            Else
                Me.uxSplitContainer.Panel2Collapsed = True
            End If
        End Function

        ''' <summary>
        ''' Number of graph panes has changed
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Private Sub uxZedGraphContextMenuGraphCount_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs)
            Dim menuitem As ToolStripComboBox = CType(sender, ToolStripComboBox)

            mGraphSettings.PaneCount = CType(menuitem.SelectedItem, States.comboBoxItem).Value
            'Dim menuItem As Controls.ToolStripNumericUpDown = CType(sender, Controls.ToolStripNumericUpDown)

            'mGraphSettings.PaneCount = MenuItem.Value

            RefreshNewSettings()

        End Sub

        ''' <summary>
        ''' Handles the zoom feature changing
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Private Sub uxZedGraphContextMenuZoomOnClick_Click(ByVal sender As Object, ByVal e As System.EventArgs)
            Dim menuitem As ToolStripMenuItem = CType(sender, ToolStripMenuItem)

            Me.uxZedGraph.IsEnableZoom = menuitem.Checked
            Me.uxZedGraph.IsEnableVZoom = False
            mZoomEnabled = menuitem.Checked
        End Sub

        Private Sub uxZedGraph_ContextMenuBuilder(ByVal sender As ZedGraph.ZedGraphControl, ByVal menuStrip As System.Windows.Forms.ContextMenuStrip, ByVal mousePt As System.Drawing.Point, ByVal objState As ZedGraph.ZedGraphControl.ContextMenuObjectState) Handles uxZedGraph.ContextMenuBuilder
            Dim btn As New ToolStripMenuItem("Zoom On Mouse (check)", Nothing, AddressOf uxZedGraphContextMenuZoomOnClick_Click)

            btn.CheckOnClick = True
            If mZoomEnabled Then
                btn.CheckState = CheckState.Checked
            Else
                btn.CheckState = CheckState.Unchecked
            End If

            menuStrip.Items.Add(btn)

            Dim combo As New ToolStripComboBox
            combo.Items.Add(New States.comboBoxItem("1 Graph", 1))
            For i As Integer = 2 To MaxPaneCount
                combo.Items.Add(New States.comboBoxItem(i & "how  Graphs", i))
            Next
            combo.SelectedIndex = mGraphSettings.PaneCount - 1
            menuStrip.Items.Add(combo)

            AddHandler combo.SelectedIndexChanged, AddressOf uxZedGraphContextMenuGraphCount_ValueChanged

            'Dim menuItem As New Controls.ToolStripNumericUpDown()
            'menuItem.NumericUpDown.Maximum = 10
            'menuItem.NumericUpDown.Minimum = 1
            'menuItem.Value = mGraphSettings.PaneCount
            'menuItem.Text = "Graph Count"
            'AddHandler menuItem.ValueChanged, AddressOf uxZedGraphContextMenuGraphCount_ValueChanged
            'menuStrip.Items.Add(menuItem)
        End Sub

        Private Function uxZedGraph_MouseDownEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal e As System.Windows.Forms.MouseEventArgs) As System.Boolean Handles uxZedGraph.MouseDownEvent
            Dim graphObject As Object = Nothing
            Dim graphPane As ZedGraph.GraphPane = Nothing
            Dim graphIndex As Integer
            If sender.MasterPane.FindNearestPaneObject(e.Location, sender.CreateGraphics, graphPane, graphObject, graphIndex) Then

            End If
        End Function

        Private Function uxZedGraph_MouseUpEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal e As System.Windows.Forms.MouseEventArgs) As System.Boolean Handles uxZedGraph.MouseUpEvent

        End Function

        Public Sub RefreshLog() Implements DataStream.IStreamHandle.RefreshLog
            RefreshNewSettings()
        End Sub

        Private Sub uxZedGraph_ZoomEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal oldState As ZedGraph.ZoomState, ByVal newState As ZedGraph.ZoomState) Handles uxZedGraph.ZoomEvent
            mXzoom = sender.MasterPane.Item(0).XAxis.Scale.Max - sender.MasterPane.Item(0).XAxis.Scale.Min
            RaiseEvent Restrict(Me, New BikiSoft.DataStream.StreamRestrictEventArgs(sender.MasterPane.Item(0).XAxis.Scale.Min, sender.MasterPane.Item(0).XAxis.Scale.Max))
            Debug.Print("X Zoom factor is: " & mXzoom)

            Me.uxZedGraph.SetScrollRangeFromData()

        End Sub

        Private Sub uxZedGraph_ScrollDoneEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal bar As Windows.Forms.ScrollBar, ByVal oldState As ZedGraph.ZoomState, ByVal newState As ZedGraph.ZoomState) Handles uxZedGraph.ScrollDoneEvent
            RaiseEvent Restrict(Me, New BikiSoft.DataStream.StreamRestrictEventArgs(sender.MasterPane.Item(0).XAxis.Scale.Min, sender.MasterPane.Item(0).XAxis.Scale.Max))
        End Sub

        Private Sub uxZedGraph_ScrollEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal bar As Windows.Forms.ScrollBar, ByVal oldState As ZedGraph.ZoomState, ByVal newState As ZedGraph.ZoomState) Handles uxZedGraph.ScrollProgressEvent
            Me.uxZedGraph.SetScrollRangeFromData()
        End Sub

        Private Sub uxZedGraph_MouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles uxZedGraph.MouseClick
            If Not mZoomEnabled Then
                Dim control As ZedGraph.ZedGraphControl = CType(sender, ZedGraph.ZedGraphControl)

                Debug.Print("X: {0} Y:{1} W:{2} H:{3}", control.MasterPane(0).Chart.Rect.X, control.MasterPane(0).Chart.Rect.Y, control.MasterPane(0).Chart.Rect.Width, control.MasterPane(0).Chart.Rect.Height)

                Dim point As Integer = (((e.X - control.MasterPane(0).Chart.Rect.X) / control.MasterPane(0).Chart.Rect.Width) * (control.MasterPane.Item(0).XAxis.Scale.Max - control.MasterPane.Item(0).XAxis.Scale.Min)) + control.MasterPane.Item(0).XAxis.Scale.Min

                RaiseEvent Seek(Me, New DataStream.StreamSeekEventArgs(point))
            End If
        End Sub

        Public Event Close(ByVal sender As Object, ByVal e As System.EventArgs) Implements DataStream.IStreamRecieve.Close
        Public ReadOnly Property RecieverType() As DataStream.StreamRecieveType Implements DataStream.IStreamRecieve.RecieverType
            Get
                Return DataStream.StreamRecieveType.eStreamConsumeOnly
            End Get
        End Property
    End Class

#Region "Psudo private classes"
    ''' <summary>
    ''' Stores the name of a graph pane
    ''' </summary>
    ''' <remarks></remarks>
    Public Class GraphName
        Private mName As String

        Sub New(ByVal Name As String)
            mName = Name
        End Sub

        Public ReadOnly Property Name() As String
            Get
                Return mName
            End Get
        End Property
    End Class

    ''' <summary>
    ''' Stores a collection of graph names
    ''' </summary>
    ''' <remarks></remarks>
    Public Class GraphNameCollection
        Inherits ObjectModel.Collection(Of GraphName)
    End Class
#End Region

End Namespace


